#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Flask应用工厂模式
"""

from flask import Flask
from flask_cors import CORS
from flask_restful import Api
import os
import logging
from logging.handlers import RotatingFileHandler
from dotenv import load_dotenv
from datetime import datetime
from app.utils.response_utils import create_response

# 加载环境变量
load_dotenv()

def create_app(config_name=None):
    """创建Flask应用实例"""
    
    # 创建Flask应用
    app = Flask(__name__)
    
    # 加载配置
    from config import get_config
    config_class = get_config()
    app.config.from_object(config_class)
    
    # 如果指定了配置名称，覆盖默认配置
    if config_name:
        from config import config_map
        if config_name in config_map:
            app.config.from_object(config_map[config_name])
    
    # 配置日志系统
    configure_logging(app)
    
    # 配置CORS（允许前端访问，包括AI接口）
    CORS(app, 
         origins=app.config.get('CORS_ORIGINS', ['http://localhost:5173']),
         supports_credentials=True,
         allow_headers=['Content-Type', 'Authorization', 'X-Requested-With', 'X-Request-ID'],
         expose_headers=['Content-Type', 'X-Request-ID'],
         methods=['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS', 'PATCH'],
         max_age=3600)
    
    # 创建API实例
    api = Api(app, prefix='/api')
    
    # 注册蓝图和API路由
    register_blueprints(app, api)
    
    # 注册错误处理器
    register_error_handlers(app)
    
    # 注册请求钩子
    register_hooks(app)
    
    # 初始化IP身份识别中间件
    from app.middleware.ip_middleware import IPIdentityMiddleware
    ip_middleware = IPIdentityMiddleware(app)
    app.logger.info("IP身份识别中间件已初始化")
    
    # 初始化数据库连接
    from app.database import init_database
    if not init_database(app):
        app.logger.error("数据库初始化失败")
    
    return app

def register_blueprints(app, api):
    """注册蓝图和API路由"""
    
    # 导入API资源
    from app.api.articles import ArticleListAPI, ArticleDetailAPI, ChapterListAPI, ChapterArticlesAPI
    from app.api.search import SearchAPI, SearchSuggestionsAPI
    from app.api.favorites import FavoriteListAPI, FavoriteAPI
    from app.api.history import SearchHistoryAPI
    from app.api.health import HealthCheckAPI
    from app.api.ai import (
        ArticleExplanationAPI, 
        LegalQuestionAPI, 
        AISearchSuggestionsAPI, 
        LegalScenarioAPI, 
        AIHealthAPI
    )
    
    # 注册条文相关API
    api.add_resource(ArticleListAPI, '/articles')
    api.add_resource(ArticleDetailAPI, '/articles/<string:article_id>')
    api.add_resource(ChapterListAPI, '/articles/chapters')
    api.add_resource(ChapterArticlesAPI, '/articles/chapter/<int:chapter_number>')
    
    # 注册搜索相关API
    api.add_resource(SearchAPI, '/search')
    api.add_resource(SearchSuggestionsAPI, '/search/suggestions')
    
    # 注册收藏相关API
    api.add_resource(FavoriteListAPI, '/favorites')
    api.add_resource(FavoriteAPI, '/favorites/<string:favorite_id>')
    
    # 注册搜索历史API
    api.add_resource(SearchHistoryAPI, '/search/history')
    
    # 注册健康检查API
    api.add_resource(HealthCheckAPI, '/health')
    
    # 注册AI相关API
    api.add_resource(ArticleExplanationAPI, '/ai/explain')
    api.add_resource(LegalQuestionAPI, '/ai/question')
    api.add_resource(AISearchSuggestionsAPI, '/ai/suggestions')
    api.add_resource(LegalScenarioAPI, '/ai/scenario')
    api.add_resource(AIHealthAPI, '/ai/health')
    
    # 调试端点：显示当前用户ID
    @app.route('/debug/user')
    def debug_user():
        """调试用户ID"""
        from app.middleware.ip_middleware import get_current_user_id, get_current_user_ip
        user_id = get_current_user_id()
        user_ip = get_current_user_ip()
        return create_response(
            success=True,
            data={
                'user_id': user_id,
                'user_ip': user_ip,
                'request_ip': request.remote_addr,
                'forwarded_for': request.headers.get('X-Forwarded-For'),
                'real_ip': request.headers.get('X-Real-IP')
            },
            message='用户信息调试'
        )
    
    # 健康检查端点
    @app.route('/health')
    def health_check():
        """健康检查端点"""
        try:
            # 检查数据库连接
            from app.database import get_database_status
            db_status = get_database_status()
            
            health_data = {
                'status': 'healthy',
                'timestamp': datetime.now().isoformat(),
                'version': '1.0.0',
                'environment': app.config.get('ENV', 'development'),
                'database': db_status
            }
            
            return create_response(
                success=True,
                data=health_data,
                message='民法典H5应用后端服务正常运行'
            )
        except Exception as e:
            app.logger.error(f'Health check failed: {str(e)}')
            return create_response(
                success=False,
                error={
                    'code': 'HEALTH_CHECK_FAILED',
                    'message': '健康检查失败',
                    'details': str(e) if app.debug else '服务异常'
                },
                status_code=503
            )

def register_error_handlers(app):
    """注册错误处理器"""
    
    @app.errorhandler(400)
    def bad_request(error):
        app.logger.warning(f'Bad request: {str(error)}')
        return create_response(
            success=False,
            error={
                'code': 'BAD_REQUEST',
                'message': '请求参数错误',
                'details': str(error)
            },
            status_code=400
        )
    
    @app.errorhandler(404)
    def not_found(error):
        app.logger.info(f'Resource not found: {str(error)}')
        return create_response(
            success=False,
            error={
                'code': 'NOT_FOUND',
                'message': '请求的资源不存在',
                'details': str(error)
            },
            status_code=404
        )
    
    @app.errorhandler(500)
    def internal_error(error):
        app.logger.error(f'Internal server error: {str(error)}')
        return create_response(
            success=False,
            error={
                'code': 'INTERNAL_SERVER_ERROR',
                'message': '服务器内部错误',
                'details': str(error) if app.debug else '请联系管理员'
            },
            status_code=500
        )
    
    @app.errorhandler(429)
    def rate_limit_exceeded(error):
        app.logger.warning(f'Rate limit exceeded: {str(error)}')
        return create_response(
            success=False,
            error={
                'code': 'RATE_LIMIT_EXCEEDED',
                'message': '请求频率过高，请稍后再试',
                'details': str(error)
            },
            status_code=429
        )

def register_hooks(app):
    """注册请求钩子"""
    
    @app.before_request
    def before_request():
        """请求前处理"""
        pass
    
    @app.after_request
    def after_request(response):
        """请求后处理"""
        # 添加响应头
        response.headers['X-Content-Type-Options'] = 'nosniff'
        response.headers['X-Frame-Options'] = 'DENY'
        response.headers['X-XSS-Protection'] = '1; mode=block'
        
        return response

def configure_logging(app):
    """配置日志系统"""
    
    if not app.debug and not app.testing:
        # 确保日志目录存在
        log_dir = os.path.dirname(app.config.get('LOG_FILE', 'logs/app.log'))
        if not os.path.exists(log_dir):
            os.makedirs(log_dir)
        
        # 配置文件日志处理器
        file_handler = RotatingFileHandler(
            app.config.get('LOG_FILE', 'logs/app.log'),
            maxBytes=10240000,  # 10MB
            backupCount=10
        )
        file_handler.setFormatter(logging.Formatter(
            '%(asctime)s %(levelname)s: %(message)s [in %(pathname)s:%(lineno)d]'
        ))
        file_handler.setLevel(logging.INFO)
        app.logger.addHandler(file_handler)
    
    # 设置日志级别
    log_level = getattr(logging, app.config.get('LOG_LEVEL', 'INFO'))
    app.logger.setLevel(log_level)
    app.logger.info('民法典H5应用后端启动完成')

def serialize_datetime(obj):
    """递归序列化datetime对象"""
    if isinstance(obj, datetime):
        return obj.isoformat()
    elif isinstance(obj, dict):
        return {key: serialize_datetime(value) for key, value in obj.items()}
    elif isinstance(obj, list):
        return [serialize_datetime(item) for item in obj]
    else:
        return obj
